﻿#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QtWin>
#include <QDebug>
#include <qmessagebox.h>
#include<QScreen>
#include<QRect>

#include "lightpoint.h"



MainWindow::MainWindow(QWidget *parent)
    : CglasseFfect(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle(u8"XCDT-控制器");
    this->setFixedSize(this->geometry().size());
    my_client = new QModbusTcpClient(this);
    my_timer = new QTimer(this);

    //设置毛玻璃效果
    this->setGlassBackgroundR(255);  //R
    this->setGlassBackgroundG(255);  //G
    this->setGlassBackgroundB(255);  //B
    this->setGlassBackgroundA(50);  //A

    //设置呼吸灯效果
    ui->lab_signalLed->setBgColor(QColor::fromRgb(255,0,0));

    connect(ui->btn_setchannel, &QPushButton::clicked, this, &MainWindow::SendChannel_Slot);
    connect(ui->btn_setspacing, &QPushButton::clicked, this, &MainWindow::SendSpacing_Slot);
    connect(ui->btn_setnumber, &QPushButton::clicked, this, &MainWindow::SendNumber_Slot);
    connect(ui->btn_start, &QPushButton::clicked, this, &MainWindow::StartMotor_Slot);
    connect(ui->btn_stop, &QPushButton::clicked, this, &MainWindow::StopMotor_Slot);
    connect(ui->btn_1, &QPushButton::clicked, this, &MainWindow::AddOne_Slot);
    connect(ui->btn_reconnect, &QPushButton::clicked, this, &MainWindow::ReConnect);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::showEvent(QShowEvent *ev)
{
    this->Connect_modbus();

}


/**
 * @brief ：连接modbus
 * @return :true and false
 */

bool MainWindow::Connect_modbus()
{
    //设置ip 和 端口
    QString ip_addr = "192.168.0.11";
    int port = 502;

    if(my_client->state() != QModbusDevice::ConnectedState)
    {
        my_client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,ip_addr);
        my_client->setConnectionParameter(QModbusDevice::NetworkPortParameter,port);
        if (!my_client->connectDevice())
        {
            return false;
        }
        else
        {
            my_timer->start(30000);
            connect(my_client, &QModbusClient::stateChanged, this,&MainWindow::StateChanged_Slot);

            return true;
        }
    }
    return true;
}

/**
 * @brief: modbus状态改变时，触发该槽
 */
void MainWindow::StateChanged_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        //定时检测连接
        connect(my_timer, &QTimer::timeout, this, &MainWindow::onConnectTimerTimeout);
        read_modbus_tcp_HoldingRegisters(1,3,1);
        qDebug()<<u8"链接成功";
        ui->lab_signalLed->setBgColor(QColor::fromRgb(0,255,0));

    }
    else
    {
        ui->lab_signalLed->setBgColor(QColor::fromRgb(255,0,0));
    }
}



/**
 * @brief 设置间距
 */
void MainWindow::SendChannel_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        int channel = ui->sp_channel->value();
        Write_modbus_tcp_HoldingRegisters(channel, 1, 1);
        Write_modbus_tcp_HoldingRegisters(1, 4, 1);
        Write_modbus_tcp_HoldingRegisters(1, 5, 1);
    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                             u8"未连接网络",
                             QMessageBox::Ok,
                             QMessageBox::Ok);
    }

}

/**
 * @brief ：设置单个通道检测物料数量
 */
void MainWindow::SendNumber_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        int number = ui->sp_number->value();
        Write_modbus_tcp_HoldingRegisters(number, 3, 1);
        Write_modbus_tcp_HoldingRegisters(1, 4, 1);
        Write_modbus_tcp_HoldingRegisters(1, 5, 1);
    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                             u8"未连接网络",
                             QMessageBox::Ok,
                             QMessageBox::Ok);
    }

}

/**
 * @brief 设置通道之间的间距
 */
void MainWindow::SendSpacing_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        int spacing = ui->sp_spacing->value();
        Write_modbus_tcp_HoldingRegisters(spacing, 2, 1);
        Write_modbus_tcp_HoldingRegisters(1, 4, 1);
        Write_modbus_tcp_HoldingRegisters(1, 5, 1);

    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                             u8"未连接网络",
                             QMessageBox::Ok,
                             QMessageBox::Ok);
    }

}

/**
 * @brief 启动电机
 */
void MainWindow::StartMotor_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        Write_modbus_tcp_HoldingRegisters(1, 5002, 1);
        Write_modbus_tcp_HoldingRegisters(1, 11, 1);
    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                             u8"未连接网络",
                             QMessageBox::Ok,
                             QMessageBox::Ok);
    }
}

/**
 * @brief ：停止电机
 */
void MainWindow::StopMotor_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        Write_modbus_tcp_HoldingRegisters(9, 5002, 1);
        Write_modbus_tcp_HoldingRegisters(2, 5002, 1);
        Write_modbus_tcp_HoldingRegisters(2, 11, 1);
    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                                   u8"未连接网络",
                                   QMessageBox::Ok,
                                   QMessageBox::Ok);
    }
}

/**
 * @brief +1+1+1+1+1
 */
void MainWindow::AddOne_Slot()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        Write_modbus_tcp_HoldingRegisters(1, 10, 1);
        QTimer *timer = new QTimer;
        timer->start(50);
        connect(timer, &QTimer::timeout, this, [=](){
            Write_modbus_tcp_HoldingRegisters(0, 10, 1);
            timer->stop();
        });
    }
    else
    {
        QMessageBox::warning(this, u8"waring",
                                   u8"未连接网络",
                                   QMessageBox::Ok,
                                   QMessageBox::Ok);
    }
}

/**
 * @brief 重新连接网络
 */
void MainWindow::ReConnect()
{
    if(my_client->state() != QModbusDevice::ConnectedState)
    {
        my_client->connectDevice();
    }
}

/**
 * @brief ：modbus心跳检测
 */
void MainWindow::onConnectTimerTimeout()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {
        Write_modbus_tcp_HoldingRegisters(1,1000,1);
    }
    else
    {
        this->Connect_modbus();
    }
}


/**
 * @brief : 向保持寄存器中写数据
 * @param value ： 写的值
 * @param star_add ：写的地址
 * @param number ： 写的位数
 */
void MainWindow::Write_modbus_tcp_HoldingRegisters(int value, int star_add,int number)
{
    quint16 number1 = static_cast<quint16>(number);
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,star_add,number1);
    int j1 = 0;
    for (uint i1 = 0; i1 < writeUnit.valueCount(); i1++) {

        if(i1 == 0){
            j1 = static_cast<int>(2*i1);
        }
        else {
            j1 = j1+3;
        }
        writeUnit.setValue(static_cast<int>(i1),value);//设置发送数据
    }

    if (auto *reply = my_client->sendWriteRequest(writeUnit, 1)) {// ui->spinBox_SerAddress->value()是server address   sendWriteRequest是向服务器写数据
        if (!reply->isFinished()) {   //reply Returns true when the reply has finished or was aborted.
            connect(reply, &QModbusReply::finished, this, [reply]() {
                if (reply->error() == QModbusDevice::ProtocolError) {
                    qDebug() << (tr(u8"Write response error: %1 (Mobus exception: 0x%2)")
                                     .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
                                 5000);
                } else if (reply->error() != QModbusDevice::NoError) {
                    qDebug()<< (tr(u8"Write response error: %1 (code: 0x%2)").
                                 arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
                }
                reply->deleteLater();
            });
        } else {
            // broadcast replies return immediately

            reply->deleteLater();
        }
    } else {
        qDebug() << (tr("Write error: ") + my_client->errorString(), 5000);
    }
}

/**
 * @brief :读取modbus,保持寄存器。
 * @param start_add：读取的起始地址
 * @param numbers：读取多少个数据
 * @param Server_ID：SerVer ID号
 */
void MainWindow::read_modbus_tcp_HoldingRegisters(int start_add, quint16 numbers, int Server_ID)
{
    if(!my_client)
        qDebug()<<u8"连接错误";
    QModbusDataUnit ReadUnit(QModbusDataUnit::HoldingRegisters,start_add,numbers);

    if (auto *reply = my_client->sendReadRequest(ReadUnit, Server_ID))     //1是Server_ID
    {

        if (!reply->isFinished())
        {
            QObject::connect(reply, &QModbusReply::finished,this,&MainWindow::ReadReady_InputRegisters);
        }
        else
        {
            delete reply;
        }
    }
}

void MainWindow::ReadReady_InputRegisters()
{
    if(my_client->state() == QModbusDevice::ConnectedState)
    {        
        auto *reply = qobject_cast<QModbusReply *>(sender());
        if (!reply){
            return ;
        }
        if (reply->error() == QModbusDevice::NoError)
        {
            const QModbusDataUnit unit = reply->result();

            for (int i = 0, total = int(unit.valueCount()); i < total; ++i)
            {
                modbus_data.append(unit.value(i));
                qDebug()<<u8"以获取数据";
                qDebug()<<modbus_data.at(i);
            }
            if(!modbus_data.isEmpty())
            {
                ui->sp_channel->setValue(modbus_data.at(0));
                ui->sp_spacing->setValue(modbus_data.at(1));
                ui->sp_number->setValue(modbus_data.at(2));
            }

        }
        else if (reply->error() == QModbusDevice::ProtocolError)
        {
            qDebug()<<u8"modbus 协议出错。";
        }
        else
        {


        }

    }
    else
    {
        qDebug()<<u8"当前未连接";
    }


}
